/**
 * Copyright (c) 2009 Collaborative Development Group, C.S. Dept., University of Bari
 *
 * All rights reserved. This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0  which accompanies this distribution, and is 
 * available at http://www.eclipse.org/legal/epl-v10.html
 */
package it.uniba.di.cdg.penelope.events;

import static it.uniba.di.cdg.penelope.events.IEventHelper.APP_EVENT;
import static it.uniba.di.cdg.penelope.util.ReflectionUtilities.getMethod;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import it.uniba.di.cdg.penelope.presenterfirst.SUT;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.osgi.service.event.Event;

/**
 * Tests for {@link EventHandlerProxy}.
 */
public class EventHandlerProxyTest {
	/**
	 * Event handler to be proxied: we verify if the event handler method is truly invoked.  
	 */
	public static class MockReceiver {
		private boolean isInvoked;
		
		@OnEvent
		public void onEventHandler( DummyEvent event ) {
			isInvoked = true;
		}

		@OnEvent
		public void onBadEventHandler( /* No event parameter! */ ) {
			isInvoked = true;
		}
		
		public boolean isInvoked() {
			return isInvoked;
		}
	}
	
	@SUT
	private EventHandlerProxy proxy;
	
	private Event event;
	
	private MockReceiver mockReceiver;
	
	private IEventHandlerProxyFactory mockFactory;
	
	@Before
	public void setupMocks() {
		// Setup a fake event: the topic id is not interesting for the proxy (only for the EventAdmin service), 
		// so we can provide a fake one
		Map<String, Object> properties = new HashMap<String, Object>();
		properties.put( APP_EVENT, new DummyEvent() );
		event = new Event( "fake/event/topic/id", properties );
		mockFactory = mock( IEventHandlerProxyFactory.class );
		mockReceiver = new MockReceiver();
		proxy = new EventHandlerProxy( mockFactory, mockReceiver );
	}
	
	@Test
	public void shouldInvokeTargetMethod() {
		final List<Method> methods = new ArrayList<Method>();
		methods.add( getMethod( MockReceiver.class, "onEventHandler", DummyEvent.class ) );
		
		when( mockFactory.getMethods( MockReceiver.class )).thenReturn( methods );			

		proxy.handleEvent( event );
		
		verify( mockFactory ).getMethods( MockReceiver.class );
		assertTrue( "Event handling method was not invoked!", mockReceiver.isInvoked() );
	}

	@Test( expected = EventHandlerInvocationException.class )
	public void shouldThrowAnExceptionIfTheMethodHasNoEventParameter() {
		final List<Method> methods = new ArrayList<Method>();
		methods.add( getMethod( MockReceiver.class, "onBadEventHandler" ) );
		
		when( mockFactory.getMethods( MockReceiver.class )).thenReturn( methods );			

		proxy.handleEvent( event );
	}
}
